Skip to content

Conversation

@rkistner
Copy link
Contributor

@rkistner rkistner commented May 7, 2025

This aims to provide more useful error messages when auth fails, by:

  1. Using our own error codes and messages, instead of the defaults from JOSE.
  2. Add additional details on the token and/or relevant configuration in the service logs (but not the error response).

Examples

For each example, the first line is in the error response, second line is in logs only.

In most of these examples, a big gain is having the token header and payload in the logs. In some cases, the details of the key that the token is compared to may also help. The cause in the logs also help.

// unknown kid
{"code":"PSYNC_S2101","status":401,"description":"Could not find an appropriate key in the keystore. The key is missing or no key matched the token KID","name":"AuthorizationError"}
"configurationDetails":"Known kid values: powersync-dev, powersync-53b1a54716","tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\"} payload: {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022}>"

// passing a static token instead of JWT
{"code":"PSYNC_S2101","status":401,"description":"Token is not a well-formed JWT. Check the token format.","name":"AuthorizationError"}
"tokenDetails":"<token with 1 parts (needs 3), length=4>"

// Correct kid, invalid key
{"code":"PSYNC_S2101","status":401,"description":"signature verification failed","name":"AuthorizationError"}
"tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022}>"

// Missing exp
{"code":"PSYNC_S2101","status":401,"description":"JWT payload is missing a required claim \"exp\"","name":"AuthorizationError"}
"tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022}>"

// JWT expired
{"code":"PSYNC_S2103","status":401,"description":"JWT has expired","name":"AuthorizationError"}
"tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022,\"exp\":1516239022}>"

// Expiry too long
{"code":"PSYNC_S2104","status":401,"description":"Token must expire in a maximum of 86400 seconds, got 230387123s","name":"AuthorizationError"}
"tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"aud\":\"powersync-dev\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022,\"exp\":1746626145}>"

// Missing 'aud'
{"code":"PSYNC_S2105","status":401,"description":"JWT payload is missing a required claim \"aud\"","name":"AuthorizationError"}
"configurationDetails":"Current configuration allows these audience values: [\"powersync-dev\",\"http://localhost:8000\"]","tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1516239022,\"exp\":1746626145}>"

// alg mismatch for a key
{"code":"PSYNC_S2101","status":401,"description":"Unexpected token algorithm HS256","name":"AuthorizationError"}
"configurationDetails":"Key kid: powersync-dev, alg: RS256, kty: RSA","tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-dev\"} payload: {\"sub\":\"1234567890\",\"aud\":\"powersync-dev\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1746626145,\"exp\":1746626145}>"

// JWKS request error
{"code":"PSYNC_S2204","status":401,"description":"JWKS request failed","name":"AuthorizationError"}
"cause":{"code":"ECONNREFUSED","message":"request to http://localhost:8000/ failed, reason: connect ECONNREFUSED 127.0.0.1:8000"},"configurationDetails":"JWKS URL: http://localhost:8000/test","tokenDetails":"<header: {\"alg\":\"HS256\",\"typ\":\"JWT\",\"kid\":\"powersync-devz\"} payload: {\"sub\":\"1234567890\",\"aud\":\"powersync-dev\",\"name\":\"John Doe\",\"admin\":true,\"iat\":1746626145,\"exp\":1746626145}>"

// Invalid JWKS response
{"code":"PSYNC_S2204","status":401,"description":"Invalid JWKS response","name":"AuthorizationError"}
"configurationDetails":"JWKS URL: https://powersync-api.journeyapps.com/api/v1/regions. Response:\n{\n  \"data\": {\n    \"regions\": [\n      {\n        \"name...

// JWKS IP issue
{"code":"PSYNC_S2204","status":401,"description":"JWKS request failed","name":"AuthorizationError"}
"cause":{"message":"request to http://localhost:8000/ failed, reason: [PSYNC_S2203] IPs in this range are not supported: 127.0.0.1"},"configurationDetails":"JWKS URL: http://localhost:8000/"

@rkistner rkistner requested a review from stevensJourney May 7, 2025 14:13
@changeset-bot
Copy link

changeset-bot bot commented May 7, 2025

🦋 Changeset detected

Latest commit: cd745f0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 14 packages
Name Type
@powersync/service-module-postgres Minor
@powersync/service-rsocket-router Minor
@powersync/service-errors Minor
@powersync/service-core Minor
@powersync/lib-services-framework Minor
@powersync/service-image Minor
@powersync/service-core-tests Patch
@powersync/service-module-mongodb-storage Patch
@powersync/service-module-mongodb Patch
@powersync/service-module-mysql Patch
@powersync/service-module-postgres-storage Patch
test-client Patch
@powersync/lib-service-mongodb Patch
@powersync/lib-service-postgres Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copy link
Collaborator

@stevensJourney stevensJourney left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. The updated error response looks really nice. The implementation looks solid from my side.

@rkistner rkistner requested a review from Copilot May 8, 2025 08:35
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR improves authentication error messaging and logging by standardizing error codes and enhancing error details across various auth‐related modules. Key changes include:

  • Extending the AuthorizationError to include finer-grained token and configuration details.
  • Updating error codes and messages in auth tests and across key collection and token verification modules.
  • Adjusting error handling and property naming (e.g. token_error vs. token_errors) for consistency.

Reviewed Changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/service-errors/src/errors.ts Updated AuthorizationError constructor to accept dynamic error codes and add detailed logging data.
packages/service-errors/src/codes.ts Added new error code definitions and documentation.
packages/service-core/test/src/auth.test.ts Updated test assertions to match the new error messages with error code prefixes.
packages/service-core/src/routes/* Refactored type definitions and error handling in auth and router files.
packages/service-core/src/auth/* Enhanced JWT verification and key store error handling with standardized error responses.
modules/module-postgres/src/auth/SupabaseKeyCollector.ts Adjusted error handling for missing JWT secrets using the new AuthorizationError.
libs/lib-services/src/router/* Updated endpoint and authorization response handling to use the standardized errors.
Comments suppressed due to low confidence (2)

packages/service-core/src/routes/router.ts:19

  • The property name was updated from 'token_errors' to 'token_error' for consistency. Verify that any references to this property in other parts of the codebase have been updated.
token_error?: ServiceError;

packages/service-core/src/routes/auth.ts:108

  • The response structure now uses 'error' instead of 'errors' to report authorization failures. Please ensure that all downstream consumers of AuthorizationResponse are updated accordingly.
error: new AuthorizationError(ErrorCode.PSYNC_S2106, 'Authentication required')

@rkistner rkistner merged commit 9dc4e01 into main May 8, 2025
21 checks passed
@rkistner rkistner deleted the auth-errors branch May 8, 2025 08:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants